package com.ushine.web.component.mybatis.decryption;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @Author: yls
 * @Date 2022/2/11 15:03
 * @Description: AES 加密工具类
 * @Version 1.0
 **/
@Slf4j
public class AesUtils {

    private AesUtils() {

    }

    /**
     * 定义 aes 加密的key
     * 密钥  必须是16位, 自定义,
     * 如果不是16位, 则会出现InvalidKeyException: Illegal key size
     * 解决方案有两种：
     * 需要安装Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files(可以在Oracle下载).
     * 设置设置key的长度为16个字母和数字的字符窜（128 Bit/8=16字符）就不报错了。
     */
    private static final String KEY = "YLSUSHINEHKLSSWS";

    private static final String IV_KEY = "YIOUSHINEHKLSSWS48115648";
    /**
     * 定义加密的编码
     */
    private static final Charset CHARSET = StandardCharsets.UTF_8;

    /**
     * 偏移量
     */
    private static final int OFFSET = 16;

    /**
     * 偏移量
     */
    private static final String TRANS_FORM_ACTION = "AES/CBC/PKCS5Padding";

    /**
     * 算法名称
     */
    private static final String ALGORITHM = "AES";


    /**
     * 功能描述:
     * 〈 加密 〉
     *
     * @param content 待加密的数据
     * @return : java.lang.String
     * @author : yls
     * @date : 2022/2/11 15:12
     */
    static String encrypt(String content) {
        return encrypt(content, KEY);
    }

    /**
     * 功能描述:
     * 〈 解密 〉
     *
     * @param content 待解密的数据
     * @return : java.lang.String
     * @author : yls
     * @date : 2022/2/11 15:12
     */
    static String decrypt(String content) {
        return decrypt(content, KEY);
    }

    /**
     * 功能描述:
     * 〈加密〉
     *
     * @param content 待加密的内容
     * @param key     秘钥
     * @return : java.lang.String
     * @author : yls
     * @date : 2022/2/11 15:16
     */
    private static String encrypt(String content, String key) {
        try {
            SecretKeySpec skey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_KEY.getBytes(), 0, OFFSET);
            Cipher cipher = Cipher.getInstance(TRANS_FORM_ACTION);
            byte[] byteContent = content.getBytes(CHARSET);
            // 初始化
            cipher.init(Cipher.ENCRYPT_MODE, skey, iv);
            byte[] result = cipher.doFinal(byteContent);
            // 加密
            return new Base64().encodeToString(result);
        } catch (Exception e) {
            log.info("加密异常：", e);
        }
        return null;
    }

    /**
     * 功能描述:
     * 〈AES（256）解密〉
     *
     * @param content 待解密的内容
     * @param key     解密
     * @return : java.lang.String
     * @author : yls
     * @date : 2022/2/11 15:16
     */
    private static String decrypt(String content, String key) {
        try {
            SecretKeySpec skey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_KEY.getBytes(), 0, OFFSET);
            Cipher cipher = Cipher.getInstance(TRANS_FORM_ACTION);
            // 初始化
            cipher.init(Cipher.DECRYPT_MODE, skey, iv);
            byte[] result = cipher.doFinal(new Base64().decode(content));
            // 解密
            return new String(result);
        } catch (Exception e) {
            log.info("exception:", e);
        }
        return null;
    }

}
